package com.topscomm.gpm;

import com.topscomm.base.BaseSystemConst;
import com.topscomm.base.pojo.BaseChangeLogEntity;
import com.topscomm.base.service.impl.BaseChangeLogService;
import com.topscomm.base.service.impl.BasePropertyService;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.IBasicDao;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.basic.util.PrimaryKeyUtil;
import com.topscomm.mis.MisService;
import com.topscomm.mms.pojo.MmsDeptExtraInfoEntity;
import com.topscomm.mms.service.impl.MmsDeptExtraInfoService;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.SpringUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.gpm.pojo.GpmProjectAppointmentEntity;
import com.topscomm.gpm.pojo.GpmProjectHistoryEntity;
import com.topscomm.gpm.pojo.GpmProjectUniversalChangeEntity;
import com.topscomm.gpm.service.impl.GpmProjectUniversalChangeService;
import com.topscomm.tap.TapEntity;
import com.topscomm.tap.common.DatacodeCache;
import com.topscomm.tap.common.SessionUserBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.configurationprocessor.json.JSONArray;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @Description TODO
 * @Classname SdService
 * @Date 2021/11/19
 * @Created by jiangtao
 */
public class GpmService<T extends GpmEntity,TDao extends IGpmDao> extends MisService<T, TDao>
implements IGpmService<T,TDao> {
	// 在baseproperty中使用属性的范围
	private static final String BASEPROPERTYSCOPE = "changelog";
	DatacodeCache datacodeCache = new DatacodeCache();
	@Autowired
	private MmsDeptExtraInfoService mmsDeptExtraInfoService;
	@Autowired
	private BasePropertyService basePropertyService;
	@Autowired
	private BaseChangeLogService baseChangeLogService;
	@Autowired
	private GpmProjectUniversalChangeService gpmProjectUniversalChangeService;

	@Override
	protected void afterSubmit(TapEntity entity, SessionUserBean sessionUserBean) {
		try {
			StringBufferProxy sql = new StringBufferProxy();
			sql.appendLineSingle("update CboApprovalFlowIns set ");
			sql.appendLineSingle("extendfield1 = (select docno from {0} "
							+ "where CboApprovalFlowIns.sourceid = {0}.id " + "and CboApprovalFlowIns.sourcetype = '{0}'),",
					entity.getTableName());
			sql.appendLineSingle("extendfield2 = (select deptcode from {0} "
							+ "where CboApprovalFlowIns.sourceid = {0}.id " + "and CboApprovalFlowIns.sourcetype = '{0}'),",
					entity.getTableName());
			sql.appendLineSingle("extendfield3 = (select usercode from {0} "
							+ "where CboApprovalFlowIns.sourceid = {0}.id " + "and CboApprovalFlowIns.sourcetype = '{0}')",
					entity.getTableName());
			sql.appendLineSingle("where sourceid = '{0}' and sourcetype='{1}'", entity.getId(), entity.getTableName());

			this.getDao().updateExecute(sql.toString());
			super.afterSubmit(entity, sessionUserBean);
		} catch (Exception e) {
			throw new ServiceException(e);
		}
	}
	/***
	 * @description: 获取部门扩展信息
	 * @param deptcode
	 * @return
	 * @author: jiangtao1
	 * @date: 2021/11/29 11:26
	 * @modify:
	 */
	@Override
	public MmsDeptExtraInfoEntity queryDeptCommonCode(String deptcode) {
		StringBufferProxy sql = new StringBufferProxy();
		if (deptcode.contains("_")) {
			deptcode = deptcode.substring(0,deptcode.indexOf('_')+5);
		} else {
			deptcode = deptcode.substring(0,4);
		}
		sql.appendSingle(" ',' || {0} || ',' like '%{1}%'", MmsDeptExtraInfoEntity.FieldDeptcode,","+deptcode+",");
		MmsDeptExtraInfoEntity deptExtraInfoEntity = mmsDeptExtraInfoService.queryObjectByWhere(sql.toString());
		return  deptExtraInfoEntity;
	}

	/**
	 * @param
	 * @return
	 * @throws
	 * @description: 生成id
	 * @author xinfushuo
	 * @date 2021/9/10
	 * @modify
	 */
	public void GenerateID(BasicEntity entity) {
		if (entity.getId() <= 0) {
			long[] arrayId = PrimaryKeyUtil.GeneIDs(entity.getTableName(), 1);
			entity.setId(arrayId[0]);
		}
	}

	/**
	 * @param
	 * @return
	 * @throws
	 * @description:
	 * @author xinfushuo
	 * @date 2021/9/10
	 * @modify
	 */
	public void GenerateDocno(BasicEntity entity) {
		long entityId = entity.getId();
		String docNo = String.valueOf(entityId);
		if (!StringUtil.isEmpty(docNo)) {
			docNo = docNo.substring(0, 6) + docNo.substring(9);
			entity.setValue("docno", docNo);
		}
	}

	/**
	 * @param
	 * @return
	 * @throws
	 * @description:
	 * @author xinfushuo
	 * @date 2021/9/10
	 * @modify
	 */
	public void GenerateCode(BasicEntity entity, String header, String codeField) {
		long entityId = entity.getId();
		String docNo = String.valueOf(entityId);
		docNo = docNo.substring(0, 6) + docNo.substring(8);
		try {
			Class<? extends Object> entityClass = entity.getClass();
			Method getprojectlevel = entityClass.getMethod("getProjectlevel");
			String projectLevel = (String) getprojectlevel.invoke(entity);
			//赋值编号 xxcode
			projectLevel = datacodeCache
					.getValueDynamic("GpmProjectLevel", projectLevel, "code", "name");
			SimpleDateFormat sdFormat = new SimpleDateFormat("yyMMdd");
			String dateCode = sdFormat.format(new Date());
			String flowCode = docNo.substring(docNo.length() - 4);
			header = header + projectLevel + dateCode + flowCode;
			entity.setValue(codeField, header);
		} catch (Exception e) {
			throw new ServiceException(e + "编号生成错误");
		}

	}

	/**
	 * @param header    : 编号头 如 PP PR PSl
	 * @param codeField : 编号列名
	 * @return
	 * @throws
	 * @description:
	 * @author xinfushuo
	 * @date 2021/9/2
	 * @modify
	 */
	public void GenerateIDAndCode(BasicEntity entity, String header, String codeField) {
		try {
			//若id未生成 生成id
			if (entity.getId() <= 0) {
				GenerateID(entity);
				//若docno已生成 则不重复生成
				String docno = ConvertUtil.convertToString(entity.getValue("docno"));
				if (StringUtil.isEmpty(docno)) {
					GenerateDocno(entity);
				}
				// 若codeField已生成，则不重复生成
				String dispCodeField = ConvertUtil.convertToString(entity.getValue(codeField));
				if (StringUtil.isEmpty(dispCodeField)) {
					GenerateCode(entity, header, codeField);
				}
			}
		} catch (Exception e) {
			throw new ServiceException(e + "编号id或docno生成失败");
		}
	}

	private String getAllParentValues(String sourceType, String sourceId, String topsourcetype, String topsourceid,
									  Map<String, Object> newMap, List<String> versionArr) throws Exception {
		StringBuffer allParentValuesStr = new StringBuffer();
		List<Map<String, Object>> allProperties = basePropertyService.getBaseProperty("AllProperty", BASEPROPERTYSCOPE);
		List<Map<String, Object>> relationSourceList = allProperties.stream()
				.filter(item -> sourceType.equals(ConvertUtil.convertToString(item.get("relationsource")))
						&& ConvertUtil.convertToString(item.get("relationkind"))
						.contains(ConvertUtil.convertToString(newMap.get("sourcetype"))))
				.collect(Collectors.toList());
		List<Map<String, Object>> parents = new ArrayList<Map<String, Object>>();
		if (relationSourceList.size() > 0) {
			this.getParentProperty(relationSourceList.get(0), allProperties, parents, newMap, versionArr);
		}
		if (parents.size() > 0) {
			for (Map<String, Object> p : parents) {
				allParentValuesStr.append(",");
				allParentValuesStr.append(p.get("parentkeystr"));
			}
			allParentValuesStr.append(",");
		}
		return allParentValuesStr.toString();
	}

	private void getParentProperty(Map<String, Object> relationSourceProperty, List<Map<String, Object>> allProperties,
								   List<Map<String, Object>> allParents, Map<String, Object> ownData, List<String> versionArr) {
		if (!StringUtil.isEmpty(ConvertUtil.convertToString(relationSourceProperty.get("relationsource")))) {
			List<Map<String, Object>> parentSources = allProperties.stream()
					.filter(item -> ConvertUtil.convertToString(relationSourceProperty.get("sourcetype"))
							.equals(ConvertUtil.convertToString(item.get("relationsource"))))
					.collect(Collectors.toList());
			if (!versionArr.contains(ConvertUtil.convertToString(relationSourceProperty.get("sourcetype")))) {
				IBasicDao basicDao;
				String serviceName = relationSourceProperty.get("sourcetype").toString().substring(0, 1).toLowerCase()
						+ relationSourceProperty.get("sourcetype").toString().substring(1) + "Dao";
				basicDao = (IBasicDao) SpringUtil.getBean(serviceName);
				List<Map<String, Object>> queryList = basicDao.queryMapByWhere(" id = '"
						+ ConvertUtil.convertToString(ownData.get(relationSourceProperty.get("relationkey"))) + "'");
				if (queryList.size() > 0) {
					Map<String, Object> parentData = queryList.get(0);
					parentData.put("parentkeystr", ConvertUtil.convertToString(relationSourceProperty.get("sourcetype"))
							+ ConvertUtil.convertToString(parentData.get("id")));
					allParents.add(parentData);
					if (parentSources.size() > 0) {
						getParentProperty(parentSources.get(0), allProperties, allParents, parentData, versionArr);
					}
				}
			}
		}
	}

	protected BaseChangeLogEntity getMainChangeLogEntity(Map<String, Object> inputMap) throws Exception {
		// 整理变量类型
		Map<String, Object> newMap = (Map<String, Object>) inputMap.get("newmap");
		Map<String, Object> oldMap = (Map<String, Object>) inputMap.get("oldmap");
		String sourceType = inputMap.get("sourcetype").toString();
		String sourceId = inputMap.get("sourceid").toString();
		String baseLogOperateType = inputMap.get("baselogoperatetype").toString();
		String topsourcetype = inputMap.get("topsourcetype").toString();
		String topsourceid = inputMap.get("topsourceid").toString();
		String newVersion = inputMap.get("version").toString();
		// 获取sourcetype对应的字段
		List<Map<String, Object>> baseProperties = basePropertyService.getBaseProperty(sourceType,
				BASEPROPERTYSCOPE);
		if (baseProperties.size() <= 0) {
			throw new ServiceException("baseproperty数据维护不正确");
		}
		// 获取标题的baseProperty
		List<Map<String, Object>> basePropertiesFilter = baseProperties.stream()
				.filter(item -> item.get("sourcetype").toString().equals(sourceType)
						&& item.get("datatype").toString().equals(BaseSystemConst.BasePropertyDataTypeEnum.Title))
				.collect(Collectors.toList());
		if (basePropertiesFilter.size() <= 0) {
			throw new ServiceException("baseproperty数据维护不正确");
		}
		Map<String, Object> titleBaseProperty = basePropertiesFilter.get(0);
		// 获取当前表的是否有分类信息的分类字段
		String sourceKindKey = "";
		String kindTitle = "";
		if (titleBaseProperty.get("relationkind") != null
				&& !StringUtil.isEmpty(ConvertUtil.convertToString(titleBaseProperty.get("relationkind")))) {
			org.json.JSONArray kindJsonArray = new org.json.JSONArray(
					ConvertUtil.convertToString(titleBaseProperty.get("relationkind")));
			org.json.JSONObject jsonObject = kindJsonArray.getJSONObject(0);
			sourceKindKey = ConvertUtil.convertToString(jsonObject.get("kindkey"));
			if (!sourceKindKey.equals("") && newMap.containsKey(sourceKindKey)
					&& newMap.get(sourceKindKey) != null) {
				String kindValue = ConvertUtil.convertToString(newMap.get(sourceKindKey));
				for (int i = 0; i < kindJsonArray.length(); i++) {
					org.json.JSONObject obj = kindJsonArray.getJSONObject(i);
					if (ConvertUtil.convertToString(obj.get("kindvalue")).equals(kindValue)) {
						kindTitle = ConvertUtil.convertToString(obj.get("kindtitle"));
					}
				}
			}
		}
		String allParentValues = "";
		List<String> versionArr = new ArrayList<String>(Arrays.asList(GpmProjectHistoryEntity.tableName, GpmProjectAppointmentEntity.tableName));
		if (versionArr.contains(topsourcetype)) {
			//递归拼接ALlParentValues
			allParentValues = this.getAllParentValues(sourceType,sourceId,topsourcetype,topsourceid,newMap,versionArr);
		}
		// 组装变更记录数据
		JSONArray content = baseChangeLogService.compareData(oldMap, newMap, baseProperties, baseLogOperateType);
		// 如果没有变更数据
		if (content.length() <= 0) {
			return null;
		}
		// 企业客户、个人客户要更新version
		BaseChangeLogEntity baseChangeLogEntity = new BaseChangeLogEntity();
		baseChangeLogEntity.setSourcetype(sourceType);
		baseChangeLogEntity.setSourceid(sourceId);
		baseChangeLogEntity.setTopsourcetype(topsourcetype);
		baseChangeLogEntity.setTopsourceid(topsourceid);
		if (!StringUtil.isEmpty(newVersion)) {
			baseChangeLogEntity.setVersion(Integer.parseInt(newVersion));
		}
		try {
			baseChangeLogEntity.setTitle(this.getTitle(baseLogOperateType, kindTitle, titleBaseProperty, newMap));
		} catch (Exception e) {
			baseChangeLogEntity.setTitle("信息");
		}
		baseChangeLogEntity.setUsername(this.getSessionUserBean().getUser().getName());
		baseChangeLogEntity.setUsercode(this.getSessionUserBean().getUser().getCode());
		baseChangeLogEntity.setOperatetype(baseLogOperateType);
		baseChangeLogEntity.setContent(content.toString());
		baseChangeLogEntity.setAllparentvalues(allParentValues);
		// 如果存在sourceKindKey
		if (!sourceKindKey.equals("") && newMap.containsKey(sourceKindKey) && newMap.get(sourceKindKey) != null) {
			baseChangeLogEntity.setSourcekind(ConvertUtil.convertToString(newMap.get(sourceKindKey)));
		}
		if (inputMap.containsKey("description") && inputMap.get("description") != null) {
			baseChangeLogEntity.setDescription(inputMap.get("description").toString());
		}
		return baseChangeLogEntity;
	}
	/**
	 *
	 * @description:获取标题
	 * @param baselogoperatetype
	 * @param kindTitle
	 * @param titleBaseProperty
	 * @param newMap
	 * @return
	 * @author: jiangtao1
	 * @date: 2021年6月22日下午2:57:08
	 * @modify:
	 */
	private String getTitle(String baselogoperatetype, String kindTitle, Map<String, Object> titleBaseProperty,
							Map<String, Object> newMap) {
		StringBuilder title = new StringBuilder();
		switch (baselogoperatetype) {
			case BaseSystemConst.BaseLogOperateTypeEnum.Add:
				title.append("新增");
				break;
			case BaseSystemConst.BaseLogOperateTypeEnum.Edit:
				title.append("编辑");
				break;
			case BaseSystemConst.BaseLogOperateTypeEnum.Del:
				title.append("删除");
				break;
			default:
				break;
		}
		title.append(" \"");
		title.append(parsingTitle(titleBaseProperty.get("name").toString(), newMap));
		if (!StringUtil.isEmpty(kindTitle)) {
			title.append("-");
			title.append(kindTitle);
		}
		title.append("\"");
		return title.toString();
	}

	/**
	 *
	 * @description:解析带有{}的标题
	 * @param baseTitle
	 * @param newMap
	 * @return
	 * @author: jiangtao1
	 * @date: 2021年6月22日下午2:56:54
	 * @modify:
	 */
	private String parsingTitle(String baseTitle, Map<String, Object> newMap) {
		String regex = "\\{([^}])*\\}";
		Pattern pattern = Pattern.compile(regex);
		Matcher matcher = pattern.matcher(baseTitle);
		ArrayList<String> replaceKeys = new ArrayList<String>();
		while (matcher.find()) {
			String key = matcher.group();
			String formatKey = key.replace("{", "");
			formatKey = formatKey.replace("}", "");
			if (newMap.containsKey(formatKey) && newMap.get(formatKey) != null) {
				baseTitle = baseTitle.replace(key, newMap.get(formatKey).toString());
			} else {
				baseTitle = baseTitle.replace(key, "");
			}
		}
		return baseTitle;
	}

	protected void updateUniversalChange(TapEntity billEntity, String sourceType) {
		List<GpmProjectUniversalChangeEntity> changeEntityList = gpmProjectUniversalChangeService.queryByWhere("sourceid = " + billEntity.getValue("id") +
				" and sourcetype = '" + sourceType + "' and version = "+billEntity.getValue("version")+"  order by id desc");
		if(changeEntityList.size()>0) {
			Map<String, Object> updateMap = new HashMap<String, Object>();
			updateMap.put(GpmProjectUniversalChangeEntity.FieldId, changeEntityList.get(0).getId());
			updateMap.put(GpmProjectUniversalChangeEntity.FieldState, billEntity.getValue("state"));
			updateMap.put(GpmProjectUniversalChangeEntity.FieldLatestphase, billEntity.getValue("latestphase"));
			gpmProjectUniversalChangeService.update(updateMap);
		}
	}

	protected void updateUniversalChange(TapEntity billEntity, Date docDate, String sourceType) {
		List<GpmProjectUniversalChangeEntity> changeEntityList = gpmProjectUniversalChangeService.queryByWhere("sourceid = " + billEntity.getValue("id") +
				" and sourcetype = '" + sourceType + "' and version = "+billEntity.getValue("version")+"  order by id desc");
		if(changeEntityList.size()>0) {
			Map<String, Object> updateMap = new HashMap<String, Object>();
			updateMap.put(GpmProjectUniversalChangeEntity.FieldId, changeEntityList.get(0).getId());
			updateMap.put(GpmProjectUniversalChangeEntity.FieldState, billEntity.getValue("state"));
			updateMap.put(GpmProjectUniversalChangeEntity.FieldLatestphase, billEntity.getValue("latestphase"));
			updateMap.put(GpmProjectUniversalChangeEntity.FieldSubmitdate, docDate);
			gpmProjectUniversalChangeService.update(updateMap);
		}
	}
}
